﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Windows;
using System.Windows.Media.Imaging;
using zTalk.Network;
using System.Configuration;

namespace zTalk
{
    public partial class App : System.Windows.Application
    {
        public static UserItem User { get; set; }
        public static SocketClient Client { get; set; }
        public static PacketHandlerClient Handler { get; set; }
        public static System.Windows.Forms.NotifyIcon TrayIcon { get; set; }

        public App()
        {
            App.Client = new SocketClient();
            App.Client.Host = ConfigurationManager.AppSettings["Host"];
            App.Client.Port = int.Parse(ConfigurationManager.AppSettings["Port"]);

            App.Handler = new PacketHandlerClient();
            PacketReader.Handler = App.Handler;

            TrayIcon = new System.Windows.Forms.NotifyIcon();
            TrayIcon.Text = "zTalk";
            
            string uri = "pack://application:,,,/zTalk;component/resources/icon.ico";
            Stream iconStream = Application.GetResourceStream(new Uri(uri)).Stream;
            TrayIcon.Icon = new System.Drawing.Icon(iconStream);
            iconStream.Close();
            
            TrayIcon.Visible = false;
            TrayIcon.ContextMenu = new System.Windows.Forms.ContextMenu();
            TrayIcon.ContextMenu.MenuItems.Add("Open zTalk");
            TrayIcon.ContextMenu.MenuItems.Add("-");
            TrayIcon.ContextMenu.MenuItems.Add("Exit");
            TrayIcon.BalloonTipText = "You can quit zTalk from here";
            TrayIcon.BalloonTipTitle = "Welcome to zTalk";

            Exit += new ExitEventHandler(App_Exit);
        }

        void App_Exit(object sender, ExitEventArgs e)
        {
            Client.Close();
        }

        public static string Sha1(string input)
        {
            return BitConverter.ToString(
                new SHA1CryptoServiceProvider().ComputeHash(Encoding.Default.GetBytes(input))
            ).Replace("-", String.Empty);
        }

        public static BitmapImage DecodeAvatar(string avatar64)
        {
            if (avatar64 == null || avatar64 == string.Empty)
            {
                return new BitmapImage(
                    new Uri("pack://application:,,,/zTalk;component/resources/proto.png")
                );
            }

            byte[] bin = Convert.FromBase64String(avatar64);
            MemoryStream ms = new MemoryStream(bin);

            BitmapImage img = new BitmapImage();
            img.BeginInit();
            img.StreamSource = new MemoryStream(ms.ToArray());
            img.EndInit();

            return img;
        }

        public static void SendUserChange()
        {
            Packet packet = Packet.Create(
                Opcodes.USER_CHANGE,
                Json.Encode<UserItem>(User)
            );
            Client.SendPacket(packet);
        }

        [StructLayout(LayoutKind.Sequential)]
        struct LASTINPUTINFO
        {
            public static readonly int SizeOf = 
                Marshal.SizeOf(typeof(LASTINPUTINFO));

            [MarshalAs(UnmanagedType.U4)]
            public int cbSize;
            [MarshalAs(UnmanagedType.U4)]
            public UInt32 dwTime;
        }

        [DllImport("user32.dll")]
        static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        public static int GetLastInputTime()
        {
            int idleTime = 0;
            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = Marshal.SizeOf(lastInputInfo);
            lastInputInfo.dwTime = 0;

            int envTicks = Environment.TickCount;

            if (GetLastInputInfo(ref lastInputInfo))
            {
                int lastInputTick = (int)lastInputInfo.dwTime;

                idleTime = envTicks - lastInputTick;
            }

            return ((idleTime > 0) ? (idleTime / 1000) : idleTime);
        }
    }
}
